﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using xxpl1.Utils;

namespace xxpl1.Cache
{
    public class VirtualDiskCache:IDisposable
    {
        private readonly Dictionary<string, byte[]> memoryCache = new Dictionary<string, byte[]>();
        private readonly Dictionary<string, DateTime> expirationInfo = new Dictionary<string, DateTime>();
        private readonly Timer expirationTimer;
        private readonly VirtualDisk virtualDisk;

        public VirtualDiskCache()
        {
            expirationTimer = new Timer(Expiration, this, 0, 120000);
            virtualDisk = File.Exists(Path.Combine(Environment.CurrentDirectory, "cache.mdx"))
                        ? VirtualDisk.LoadFromImage(Path.Combine(Environment.CurrentDirectory, "cache.mdx"))
                        : VirtualDisk.CreateVirtualDisk("cache", 50 * 1024 * 1024);
        }



        public bool Contains(string key)
        {
            bool result = expirationInfo.ContainsKey(key);

            Statistic.AddCacheHit(result);

            return result;
        }

        public byte[] Get(string key)
        {
            byte[] response = memoryCache[key];

            if (response == null)
            {
                response = virtualDisk.ReadFile(key);
                if (response == null)
                {
                    expirationInfo.Remove(key);
                }
            }
            return response;
        }

        public void Set(string key, byte[] content, DateTime expire)
        {
            memoryCache.Add(key, content);

            expirationInfo.Add(key, expire);

            virtualDisk.AddFile(key, content);
        }

        private void Expiration(object state)
        {
            List<string> exp = (from pair in expirationInfo where pair.Value < DateTime.UtcNow select pair.Key).ToList();

            foreach (string key in exp)
            {
                expirationInfo.Remove(key);
                memoryCache.Remove(key);
                virtualDisk.DeleteFile(key);
            }
        }

        public void Dispose()
        {
            expirationTimer.Dispose();
            virtualDisk.Dispose();
        }
    }
}
